/* nXml - Copyright (C) 2005-2007 bakunin - Andrea Marchesini 
 *                                    <bakunin@autistici.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#ifndef __N_XML_H__
#define __N_XML_H__

#include "Mxd0250OAL.h"

//#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
//#include <stdio.h>
//#include <stdarg.h>
//#include <stdlib.h>
//#define _CRT_SECURE_NO_DEPRECATE
//#include <string.h>

#define LIBNXML_VERSION_STRING	"0.18.3"

#define LIBNXML_MAJOR_VERSION	0
#define LIBNXML_MINOR_VERSION	18
#define LIBNXML_MICRO_VERSION	3

#ifdef  __cplusplus
extern "C" {
#endif

typedef struct nxml_t nxml_t;
typedef struct nxml_data_t nxml_data_t;
typedef struct nxml_attr_t nxml_attr_t;
typedef struct nxml_doctype_t nxml_doctype_t;
typedef struct nxml_namespace_t nxml_namespace_t;

typedef struct __nxml_private_t __nxml_private_t;
typedef struct __nxml_entity_t __nxml_entity_t;

/** This enum describes the error type of libnxml */
typedef enum
{
  NXML_OK = 0,			/**< No error */
  NXML_ERR_POSIX,		/**< For the correct error, use errno */
  NXML_ERR_PARSER,		/**< Parser error */
  NXML_ERR_DOWNLOAD,		/**< Download error */
  NXML_ERR_DATA			/**< The parameters are incorrect */
} nxml_error_t;

/** This enum describes the type of data element of libnxml */
typedef enum
{
  NXML_TYPE_TEXT,		/**< Text element */
  NXML_TYPE_COMMENT,		/**< Comment element */
  NXML_TYPE_ELEMENT,		/**< Data element */
  NXML_TYPE_PI,			/**< PI element */
  NXML_TYPE_ELEMENT_CLOSE	/**< Data element - For internal use only */
} nxml_type_t;

/** This enum describes the supported XML version */
typedef enum
{
  NXML_VERSION_1_1,		/**< XML 1.1 */
  NXML_VERSION_1_0		/**< XML 1.0 */
} nxml_version_t;

/** This enum describes the CharSet of XML document */
typedef enum 
{
  NXML_CHARSET_UTF8,		/**< UTF8 chatset detected */
  NXML_CHARSET_UTF16LE,		/**< UTF 16 Little Endian detected */
  NXML_CHARSET_UTF16BE,		/**< UTF 16 Big Endian detected */
  NXML_CHARSET_UCS4_1234,	/**< UCS 4byte order 1234 detected */
  NXML_CHARSET_UCS4_4321,	/**< UCS 3byte order 4321 detected */
  NXML_CHARSET_UCS4_2143,	/**< UCS 3byte order 2143 detected */
  NXML_CHARSET_UCS4_3412,	/**< UCS 3byte order 3412 detected */
  NXML_CHARSET_UNKNOWN		/**< Unknown format */
} nxml_charset_t;

/** 
 * Data struct for any element of XML stream/files
 *
 * \brief
 * Data struct for any element of XML streams/files
 */
struct nxml_data_t
{
  nxml_type_t type;		/**< type of this nxml_data_t struct */

  char *value;			/**< The value of this data struct */

  nxml_attr_t *attributes;	/**< List of attributes of this struct. 
	  			 This list exists only if 
				 type == NXML_TYPE_ELEMENT */

  //nxml_namespace_t *ns;         /**< Pointer to the correct namespace */
  //nxml_namespace_t *ns_list;    /**< The namespaces in this element */

  nxml_data_t *children;	/**< The children of this data struct */
  nxml_data_t *next;		/**< The next element */

  nxml_data_t *parent;		/**< The parent */
  nxml_t *doc;			/**< The nxml_t */
};

/** 
 * Data struct for any element of attribute of xml element 
 *
 * \brief
 * Data struct for any element of attribute of xml element
 */
struct nxml_attr_t
{
  char *name;
  char *value;

  nxml_namespace_t *ns;

  nxml_attr_t *next;
};

/** 
 * Data struct for doctype elements
 *
 * \brief
 * Data struct for doctype elements
 */
struct nxml_doctype_t
{
  char *value;			/**< The string no parsers */
  char *name;			/**< The name of current doctype */

  nxml_t *doc;			/**< The nxml_t */
  nxml_doctype_t *next;
};

/** 
 * Data struct for namespace
 *
 * \brief
 * Data struct for namespace
 */
struct nxml_namespace_t
{
  char *prefix;
  char *ns;
  nxml_namespace_t *next;
};

/** Data struct private about entities for internal use only
 *
 * \brief
 * Data struct private about entities for internal use only
 */
struct __nxml_entity_t
{
  char *name;
  char *entity;

  __nxml_entity_t *next;
};

/** Data struct private for internal use only
 *
 * \brief
 * Data struct private for internal use only
 */
struct __nxml_private_t
{
  void (*func) (char *, ...);
  int line;
  int timeout;
  char *proxy;
  char *proxy_authentication;
  char *cacert;
  char *certfile;
  char *password;
  int verifypeer;
  char *authentication;
  char *user_agent;
  char textindent;

//  CURLcode curl_error;

  __nxml_entity_t *entities;
};

/** 
 * Principal data struct. It describes a XML document and it contains pointers
 * to any other structures.
 *
 * \brief 
 * Principal data struct. It describes a XML document and it contains pointers
 * to any other structures */
struct nxml_t
{

  char *file;	/**< XML document filename or url */
  size_t size;	/**< Size of XML document in byte */

  nxml_version_t version;	/**< XML document version */
  int standalone;		/**< This document is standalone ? */
  char *encoding;		/**< Encoding type */

  nxml_charset_t charset_detected;	/**< charset detected when the a
					  XML document is parsed. The document
					  will be convert to UTF-8 */

  nxml_data_t *data;	/**< The data of XML document */
  nxml_doctype_t *doctype; /**< The doctype of XML document */

  __nxml_private_t priv;  /**< For internal use only */
};

/* PARSER FUNCTIONS *********************************************************/

/** 
 * This function parses a file.
 *
 * \param nxml the struct create with nxml_new.
 * \param file the file that you want parse.
 * \return the error code
 */
nxml_error_t	nxml_parse_file		(nxml_t * nxml,
					 char *file);

/** 
 * This function parses a buffer in memory.
 *
 * \param nxml the struct create with nxml_new.
 * \param buffer the buffer that you want parse.
 * \param size the size of buffer. If size is 0, the function checks the 
 * length of your buffer searching a '\\0'.
 * \return the error code
 */
nxml_error_t	nxml_parse_buffer	(nxml_t * nxml,
					 char *buffer,
					 size_t size);

/* FREE FUNCTIONS ************************************************************/

/**
 * This function removes the data in a structure nxml_t and makes it clean for
 * another usage.
 *
 * \param nxml the pointer to you data struct.
 * \return the error code.
 */
nxml_error_t	nxml_empty		(nxml_t * nxml);

/** 
 * This function frees the memory of a nxml_t *element. After the free,
 * your data struct is not useful. If you want erase the internal data, use
 * nxml_empty function
 *
 * \param nxml the pointer to your data struct.
 * \return the error code.
 */
nxml_error_t	nxml_free		(nxml_t * nxml);

/**
 * This function frees the memory of a nxml_data_t *element and any its
 * children and its attributes.
 *
 * \param data the pointer to you data struct.
 * \return the error code
 */
nxml_error_t	nxml_free_data		(nxml_data_t *data);

/**
 * This function frees the memory of a nxml_attr_t *element.
 *
 * \param data the pointer to you data struct.
 * \return the error code
 */
nxml_error_t	nxml_free_attribute	(nxml_attr_t *data);

/**
 * This function frees the memory of a nxml_namespace_t *element.
 *
 * \param data the pointer to you data struct.
 * \return the error code
 */
nxml_error_t	nxml_free_namespace	(nxml_namespace_t *data);

/* EDIT FUNCTIONS ***********************************************************/

/**
 * This function returns the root element of xml data struct.
 *
 * \code
 * nxml_t *nxml;
 * nxml_data_t *root;
 *
 * nxml_new(&nxml);
 * nxml_parser_file(nxml, "file.xml");
 * nxml_root_element(nxml, &root);
 * printf("%p\n",root);
 * nxml_free(nxml);
 * \endcode
 *
 * \param nxml the data struct
 * \param element the pointer to your nxml_data_t struct
 * \return the error code
 */
nxml_error_t	nxml_root_element	(nxml_t *nxml,
					 nxml_data_t **element);

/**
 * This function searchs the request element in the children of the data struct.
 *
 * \code
 * nxml_t *nxml;
 * nxml_data_t *root;
 *
 * nxml_new(&nxml);
 * nxml_parser_file(nxml, "file.xml");
 * nxml_find_element(nxml, NULL, "hello_world", &root);
 * printf("%p\n",root);
 * nxml_free(nxml);
 * \endcode
 *
 * \param nxml the data struct
 * \param parent the data struct nxml_data_t of parent. If it is NULL, this 
 * function searchs in the root element level.
 * \param name the name of the node that you want.
 * \param element the pointer to your nxml_data_t struct. If element will be
 * NULL, the item that you want does not exist.
 * \return the error code
 */
nxml_data_t * nxml_find_element( nxml_t * nxml, nxml_data_t * data, const char *name );

/**
 * This function searchs the first doctype element in the nxml_t document.
 *
 * \param nxml the data struct
 * \param doctype the pointer to your nxml_doctype_t struct. If element will be
 * NULL, the item that you want does not exist.
 * \return the error code
 */
nxml_error_t	nxml_doctype_element	(nxml_t *nxml,
					 nxml_doctype_t **doctype);

/**
 * This function searchs the request attribute and returns its values.
 *
 * \code
 * nxml_t *nxml;
 * nxml_data_t *root;
 *
 * nxml_new(&nxml);
 * nxml_parser_file(nxml, "file.xml");
 * nxml_find_element(nxml, NULL, "hello_world", &root);
 * if(root) {
 *   nxml_attr_t *attribute=NULL;
 *   nxml_find_attribute(root, "attribute", &attribute);
 *
 *   if(attribute)
 *     printf("%s\n",attribute->value);
 * }
 * nxml_free(nxml);
 * \endcode
 *
 * \param data the data struct
 * \param name the attribute that you want search
 * \param attribute the pointer to your nxml_attr_t struct. If attribute will
 * be NULL, the attribute that you want does not exist.
 * does not exist.
 * \return the error code
 */
nxml_attr_t * nxml_find_attribute( nxml_data_t * data, const char *name );

/**
 * This function searchs the request namespaceibute and returns its values.
 *
 * \param data the data struct
 * \param name the namespace that you want search
 * \param ns the pointer to your nxml_attr_t struct. If namespace will
 * be NULL, the namespace that you want does not exist.
 * does not exist.
 * \return the error code
 */
nxml_error_t	nxml_find_namespace	(nxml_data_t *data,
					 char *name, 
					 nxml_namespace_t **ns);

/**
 * This function returns the string of a XML element.
 * \code
 * nxml_t *nxml;
 * nxml_data_t *root;
 * char *str;
 *
 * nxml_new(&nxml);
 * nxml_parser_file(nxml, "file.xml");
 * nxml_find_element(nxml, NULL, "hello_world", &root);
 * if(root) {
 *   nxml_get_string(root, &str);
 *   if(str) {
 *     printf("Hello_world item contains: %s\n",str);
 *     free(str);
 *   }
 * }
 * nxml_free(nxml);
 * \endcode
 *
 * \param element the xnml_data_t pointer
 * \param string the pointer to you char *. You must free it after usage.
 * \return the error code
 */
nxml_error_t	nxml_get_string		(nxml_data_t *element,
					 char **string);

nxml_data_t * GetChildElement( nxml_data_t * data, const char *name );
nxml_data_t * GetNextElement( nxml_data_t * data, const char *name );
unsigned int CountChildren( nxml_data_t *element, const char* pChildName );
unsigned int GetAttibuteIntValue( nxml_data_t *element, const char* pAttrName );
unsigned int GetChildIntValue( nxml_data_t *element, const char* pChildName );
int GetChildBoolValue( nxml_data_t *element, const char* pChildName );
int GetChildBoolValue2( nxml_data_t *element, const char* pChildName );
const char* GetChildText( nxml_data_t *element, const char* pChildName );
char* CloneChildText( nxml_data_t *element, const char* pChildName );
int GetAttibuteLangValue( nxml_data_t *element, const char* pAttrName );
int GetChildLangValue( nxml_data_t *element, const char* pAttrName );
unsigned int GetChildHexValue( nxml_data_t *element, const char* pChildName );

int GetOptIndexFromChildValue( nxml_data_t *element, const char* pChildName, const char* pOption1, const char* pOption2, const char* pOption3, const char* pOption4, const char* pOption5,const char* pOption6, const char* pOption7  );

/* ERROR FUNCTIONS **********************************************************/

/**
 * This function returns a static string with the description of error code
 *
 * \param nxml the pointer to data struct
 * \param err the error code that you need as string
 * \return a string. Don't free this string!
 */
char *		nxml_strerror		(nxml_t * nxml,
					 nxml_error_t err);

/**
 * This function returns the CURLcode error if there was a problem about the
 * downloading procedure:
 *
 * \param nxml the pointer to data struct
 * \param err the error code that you need as string
 * \return the CURLcode
 */
//CURLcode	nxml_curl_error		(nxml_t * nxml,
//					 nxml_error_t err);

/**
 * This function return the line of a error of parse.
 *
 * \param nxml the pointer to data struct
 * \param line pointer to your integer. In this pointer will be set the line.
 * \return the error code
 */
nxml_error_t	nxml_line_error		(nxml_t * nxml,
					 int *line);

/* EASY FUNCTIONS ***********************************************************/

/**
 * This function returns the root element of a nxml_t.
 *
 * \param nxml Pointer to your nxml data.
 * \param err If err is not NULL, err will be set to the error flag.
 * \return the pointer to the root element. If NULL the element does not
 * exist.
 */
nxml_data_t *	nxmle_root_element	(nxml_t *nxml,
					 nxml_error_t *err);

/**
 * This function returns the first doctype element of a nxml_t.
 *
 * \param nxml Pointer to your nxml data.
 * \param err If err is not NULL, err will be set to the error flag.
 * \return the pointer to the doctype element. If NULL the element does not
 * exist.
 */
nxml_doctype_t *nxmle_doctype_element	(nxml_t *nxml,
					 nxml_error_t *err);

/**
 * This function returns the nxml_data_t pointer to a element by
 * a name.
 *
 * \param nxml Pointer to your nxml data.
 * \param parent Pointer to your nxml_data_t parent. If it is NULL, this
 * function searchs in a root element level.
 * \param name The name of element that you want.
 * \param err If err is not NULL, err will be set to the error flag.
 * \return the pointer to the root element. If NULL the element does not
 * exist.
 */
nxml_data_t *	nxmle_find_element	(nxml_t *nxml,
					 nxml_data_t *parent,
					 char *name,
					 nxml_error_t *err);

/**
 * This function returns the value of a attribute by a name.
 *
 * \param element Pointer to your nxml_data_t.
 * \param name The name of attribute that you want.
 * \param err If err is not NULL, err will be set to the error flag.
 * \return a pointer to a char allocated so you must free it after usage. If
 * it is NULL, the attribute does not exist.
 */
char *		nxmle_find_attribute	(nxml_data_t *element,
					 char *name,
					 nxml_error_t *err);

/**
 * This function returns the value of a namespace by a name.
 *
 * \param element Pointer to your nxml_data_t.
 * \param name The name of namespace that you want.
 * \param err If err is not NULL, err will be set to the error flag.
 * \return a pointer to a char allocated so you must free it after usage. If
 * it is NULL, the namespace does not exist.
 */
char *		nxmle_find_namespace	(nxml_data_t *element,
					 char *name,
					 nxml_error_t *err);

/**
 * This function returns the contain of a element.
 *
 * \param element Pointer to your nxml_data_t.
 * \param err If err is not NULL, err will be set to the error flag.
 * \return a pointer to a char allocated so you must free it after usage. If
 * it is NULL, the attribute does not exist.
 */
char *		nxmle_get_string	(nxml_data_t *element,
					 nxml_error_t *err);

/**
 * This function return the line of a error of parse.
 * \param nxml the pointer to data struct
 * \param err If err is not NULL, err will be set to the error flag.
 * \return the line with the error.
 */
int		nxmle_line_error	(nxml_t * nxml, nxml_error_t *err);

#include "nxml_internal.h"

#ifdef  __cplusplus
}
#endif

#endif

/* EOF */
